package com.platform.qujia.service.impl;

import java.math.BigDecimal;

import com.alipay.api.domain.Person;
import com.baomidou.mybatisplus.extension.api.R;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.platform.qujia.constantEnum.Constant;
import com.platform.qujia.controller.CouponController;
import com.platform.qujia.dao.*;
import com.platform.qujia.enums.*;
import com.platform.qujia.param.request.AdjustmentBalancePush;
import com.platform.qujia.pojo.AppUserInfo;
import com.platform.qujia.pojo.CouponInfo;
import com.platform.qujia.pojo.Station;
import com.platform.qujia.pojo.dto.BalanceChangeWxNotifyDTO;
import com.platform.qujia.pojo.dto.CancelCouponDto;
import com.platform.qujia.pojo.*;
import com.platform.qujia.pojo.dto.PhysicalCardIntegralDto;
import com.platform.qujia.pojo.dto.UniversalRedisMessageDto;
import com.platform.qujia.service.*;
import com.platform.qujia.utils.*;
import com.platform.qujia.utils.redis.RedisCacheUtil;
import com.platform.qujia.utils.weixinapp.WxPushUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.fastjson.JSONObject;
import com.platform.qujia.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

import static com.platform.qujia.enums.WxConsumptionMessageEnum.RECHARGE_REDUCTION_ACTIVITY;


@Slf4j
@Service
public class RedisConsumptionThemeServiceImpl implements RedisConsumptionThemeService {

    @Resource
    private WxPushUtil wxPushUtil;

    @Resource
    private AppUserInfoService appUserInfoService;

    @Resource
    private EnterpriseService enterpriseService;

    @Resource
    private CouponService couponService;
    @Autowired
    private ActivityMessagePushRecordServiceImpl activityMessagePushRecordService;
    @Autowired
    private ReductionActivityBalanceRecordService reductionActivityBalanceRecordService;


    @Resource
    private CouponWriteOffRecordsService couponWriteOffRecordsService;

    @Resource
    private RedisCacheUtil redisCacheUtil;

    @Autowired
    private ElectronicMembershipCardService electronicMembershipCardService;
    @Resource
    private StationMapper stationMapper;

    @Resource
    private OilMapper oilMapper;
    @Resource
    private CouponController couponController;
    @Autowired
    private CustomerCardUseRecordMapper customerCardUseRecordMapper;
    @Autowired
    private ReductionActivityBalanceRecordMapper reductionActivityBalanceRecordMapper;

    @Resource
    private PhysicalCardService physicalCardService;

    @Resource
    private AppUserInfoMapper appUserInfoMapper;

    /**
     * 消费（用于微信模板消息推送）
     */
    @Override
    public void couponMessageSubscription(String message, WxConsumptionMessageEnum enums) {
        log.info("消费者-----接收到的数据messag:" + message);
        switch (enums) {
            case COUPON_ISSUANCE_PUSH:
                //TODO
                log.info("COUPON_ISSUANCE_PUSH.......");
                break;
            case PERSONAL_COUPON_ISSUANCE_PUSH:
                //调整余额发券 推送消息
                log.info("PERSONAL_COUPON_ISSUANCE_PUSH..............");
                log.info("调整余额发券 推送消息");
                if (StringUtils.isNotEmpty(message)) {
                    AdjustmentBalancePush balancePush = JSONObject.parseObject(message, AdjustmentBalancePush.class);
                    //推送消息
                    AdjustmentBalancePush(balancePush);
                }
                break;
            case ACTIVITY_MESSAGE_PUSH:
                if (StringUtils.isNotEmpty(message)) {
                    ActivityMessagePushRecord activityMessagePushRecord = JSONObject.parseObject(message, ActivityMessagePushRecord.class);
                    activityMessagePushRecordService.sendWx(activityMessagePushRecord);
                }

                log.info("ACTIVITY_MESSAGE_PUSH..............");
                break;
            case OIL_PRICE_ADJUSTMENT_PUSH:
                log.info("OIL_PRICE_ADJUSTMENT_PUSH..............");
                if (StringUtils.isNotEmpty(message)) {
                    CancelCouponDto cancelCouponDto = JSONObject.parseObject(message, CancelCouponDto.class);
                    couponWriteOffRecordsService.cancelCoupon(cancelCouponDto);
                }
                break;
            case BALANCE_CHANGE_PUSH:
                log.info("电子卡余额调整消息推送");
                if (StringUtils.isNotBlank(message)) {
                    balanceChangeWxNotify(JSONObject.parseObject(message, BalanceChangeWxNotifyDTO.class));
                }
                break;
            case REFUND_MESSAGE_PUSH:
                log.info("退款消息推送");
                if (StringUtils.isNotBlank(message)) {
                    refundWxNotify(JSONObject.parseObject(message, PayOrder.class));

                }
                break;
            case INTEGRAL_MESSAGE_PUSH:
                log.info("积分变动消息推送");
                if (StringUtils.isNotBlank(message)) {
                    integralWxNotify(JSONObject.parseObject(message, CustomerPointsRecord.class));
                }
                break;
            case CHARGE_REFUND_MESSAGE_PUSH:
                log.info("充值退款消息推送");
                if (StringUtils.isNotBlank(message)) {
                    chargeRefundWxNotify(JSONObject.parseObject(message, CustomerCardUseRecord.class));
                }
                break;
            case PHYSICAL_CARD_CONSUMPTION_MESSAGE_PUSH:
                log.info("实体卡消费积分推送");
                if (StringUtils.isNotBlank(message)) {
                    physicalCardService.physicalCardIntegral(JSONObject.parseObject(message, PhysicalCardIntegralDto.class));
                }
            case MONTHLY_CONSUMPTION_REPORT_PUSH:
                log.info("月度消费账单推送");
                if (StringUtils.isNotBlank(message)) {
                    monthlyConsumptionReportWxNotify(JSONObject.parseObject(message, CustomerConsumptionReport.class));
                }
            default:
                log.info("没有找到对应的类型，消费完毕不进行后续操作");
                break;
        }

    }

    private void chargeRefundWxNotify(CustomerCardUseRecord dto) {
        boolean locked = false;
        String key = "DistributedLock_chargeRefund" + dto.getOrderNo();
        try {
            locked = redisCacheUtil.lock(key, "locked", 5);
            if (locked) {
                Map<String, String> templateParams = new HashMap<>();
                String customerPhone = dto.getMobilePhone();
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                if (StringUtils.isNotEmpty(customerPhone) && dto.getEnterpriseId() != null) {
                    AppUserInfo appUserInfo = new AppUserInfo();
                    appUserInfo.setMobilePhone(customerPhone);
                    appUserInfo.setStationId(dto.getEnterpriseId());
                    List<AppUserInfo> appUserInfos = appUserInfoService.selectAppUserInfoByMobilePhoneAndStationId(appUserInfo);


                    if (appUserInfos.size() > 0) {
                        AppUserInfo appUserInfo1 = appUserInfos.get(0);

                        //充值立减活动回退
                        BigDecimal lastRechargeAmt = dto.getLastRechargeAmt();
                        if (lastRechargeAmt == null) {
                            lastRechargeAmt = BigDecimal.ZERO;
                        }
                        ReductionActivityBalanceRecord recordQuery = new ReductionActivityBalanceRecord();
                        //判断是汽油还是柴油
                        //recordQuery.setUserId(userId.longValue());
                        recordQuery.setMobilePhone(dto.getMobilePhone());
                        recordQuery.setCardOilsType(dto.getCardOilsType());
                        Integer stationId = dto.getStationId();
                        Station station = stationMapper.selectStationById(stationId);
                        if (station != null) {
                            if (StringUtils.equals("1", station.getEnterprise().getCardUseRangeFlag())) {
                                recordQuery.setEnterpriseId(station.getEnterprise().getEnterpriseId().longValue());
                            } else {
                                recordQuery.setStationId(station.getStationId().longValue());
                            }

                            List<ReductionActivityBalanceRecord> query = reductionActivityBalanceRecordService.query(recordQuery);
                            if (query.size() > 0) {
                                ReductionActivityBalanceRecord activityBalanceRecord = query.get(0);
                                activityBalanceRecord.setRechargeAmt(lastRechargeAmt);
                                BigDecimal balance = activityBalanceRecord.getBalance();
                                BigDecimal subtract = balance.subtract(dto.getAmt());
                                if (subtract.compareTo(BigDecimal.ZERO) < 0) {
                                    subtract = BigDecimal.ZERO;
                                }
                                activityBalanceRecord.setBalance(subtract);
                                reductionActivityBalanceRecordService.update(activityBalanceRecord);
                            }

                            // 更新用户标识
                            CustomerCardUseRecord record = new CustomerCardUseRecord();
                            record.setMobilePhone(appUserInfo1.getMobilePhone());
                            record.setEnterpriseId(station.getEnterpriseId());
                            if (!org.apache.commons.lang3.StringUtils.equals("1", station.getEnterprise().getCardUseRangeFlag())) {
                                record.setStationId(station.getStationId());
                            }
                            record.setUsageType("+");
                            record.setStatus("1");
                            ArrayList<String> pts = new ArrayList<>(2);
                            pts.add(CardRecordType.MANUAL_ADD.getKey());
                            pts.add(CardRecordType.WX_RECHARGE.getKey());
                            String memberCategory;
                            Integer c = customerCardUseRecordMapper.countByExampleAndPayTypes(record, pts);
                            if (c == null || c < 2) {
                                memberCategory = Constant.MEMBER_CATEGORY_NEW_USER;
                            } else {
                                memberCategory = Constant.MEMBER_CATEGORY_OLD_USER;
                            }
                            // 更新用户标识
                            ReductionActivityBalanceRecord example = new ReductionActivityBalanceRecord();
                            if (org.apache.commons.lang3.StringUtils.equals("1", station.getEnterprise().getCardUseRangeFlag())) {
                                example.setEnterpriseId(station.getEnterprise().getEnterpriseId().longValue());
                            } else {
                                example.setStationId(station.getStationId().longValue());
                            }
                            example.setMobilePhone(appUserInfo1.getMobilePhone());
                            reductionActivityBalanceRecordMapper.updateNewUserFlagByPhoneAndEnterpriseId(example, memberCategory);

                        }


                        templateParams.put("openid", appUserInfo1.getBlogOpenid());
                        templateParams.put("stationName", dto.getStationName());
                        templateParams.put("productName", "充值退款");
                        templateParams.put("amt", dto.getAmt().toString());
                        templateParams.put("refundDate", simpleDateFormat.format(new Date()));
                        wxPushUtil.sendTemplateMsg(dto.getEnterpriseId(), templateParams, WxTemplateEnum.REFUND_SUCCESS);
                    }
                } else {
                    log.info("参数不全,发送失败,dto:{}", dto);
                    return;
                }
            } else {
                log.info("redis未获取锁");
            }
        } finally {
            if (locked) {
                redisCacheUtil.unlock(key, "locked");
            }
        }


    }

    private void AdjustmentBalancePush(AdjustmentBalancePush balancePush) {
        log.info("调整余额发券，参数：{}", balancePush);

        Station station = enterpriseService.selectStationById(Math.toIntExact(balancePush.getStationId()));

        AppUserInfo appUserInfo = new AppUserInfo();
        appUserInfo.setMobilePhone(balancePush.getUserPhone());
        appUserInfo.setStationId(station.getEnterpriseId());

        AppUserInfo appUserInfo1 = appUserInfoService.getAppUserInfo(appUserInfo);


        List<CouponInfo> couponInfoByCouponIssue = couponService.getCouponInfoByCouponIssue(balancePush.getCouponIds());
        String strSl = balancePush.getCouponIds().size() > 1 ? "......" : "";

        String couponType = null;
        if (CollectionUtils.isNotEmpty(couponInfoByCouponIssue)) {
            for (CouponInfo couponInfo : couponInfoByCouponIssue) {
                couponType = CouponTemplateCouponEnum.getKey(Integer.parseInt(couponInfo.getCouponType()));
            }
        }

        if (null == appUserInfo1.getBlogOpenid() || ObjectUtils.isEmpty(station) || StringUtils.isEmpty(couponType)) {
            //发送参数不全
            log.error("发送模板参数不全");
            return;
        }

        Map<String, String> templateParams = new HashMap<>();
        templateParams.put("openid", appUserInfo1.getBlogOpenid());
        templateParams.put("stationName", station.getStationName());
        templateParams.put("couponContent", "恭喜获得" + couponType + "1张" + strSl);
        log.info("电子卡充值-微信模板参数：{}", templateParams);
        wxPushUtil.sendTemplateMsg(station.getEnterpriseId(), templateParams, WxTemplateEnum.COUPON_DISTRIBUTION);
    }


    private void balanceChangeWxNotify(BalanceChangeWxNotifyDTO dto) {
        if (dto.getEnterpriseId() == null || StringUtils.isBlank(dto.getOpenId())) {
            log.info("参数不全,发送失败,dto:{}", dto);
            return;
        }
        Map<String, String> templateParams = new HashMap<>();
        templateParams.put("openid", dto.getOpenId());
        templateParams.put("customerNo", dto.getCustomerNo());
        templateParams.put("amt", MathUtil.add(null, dto.getAmt()) + "元");
        templateParams.put("presentAmt", MathUtil.add(null, dto.getPresentAmt()) + "元");
        templateParams.put("balance", MathUtil.add(null, dto.getBalance()) + "元");
        wxPushUtil.sendTemplateMsg(dto.getEnterpriseId(), templateParams, WxTemplateEnum.RECHARGE_SUCCESS);
        if (dto.getPresentIntegral() != null && dto.getPresentIntegral() > 0) {
            Map<String, String> integralParams = new HashMap<>();
            integralParams.put("openid", dto.getOpenId());
            if (StringUtils.isNotBlank(dto.getStationName())) {
                integralParams.put("stationName", dto.getStationName());
            } else if (dto.getStationId() != null) {
                Station station = stationMapper.selectStationById(dto.getStationId());
                if (station != null) {
                    integralParams.put("stationName", station.getStationName());
                }
            }
            integralParams.put("createTime", LocalDateTimeUtil.parse(LocalDateTime.now()));
            integralParams.put("integral", String.valueOf(MathUtil.add(null, dto.getPresentIntegral())));
            integralParams.put("totalIntegral", String.valueOf(MathUtil.add(null, dto.getTotalIntegral())));
            wxPushUtil.sendTemplateMsg(dto.getEnterpriseId(), integralParams, WxTemplateEnum.INTEGRAL_CHANGE);
        }
    }


    private void refundWxNotify(PayOrder dto) {
        Map<String, String> templateParams = new HashMap<>();
        String customerPhone = dto.getCustomerPhone();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (StringUtils.isNotEmpty(customerPhone) && dto.getEnterpriseId() != null) {
            AppUserInfo appUserInfo = new AppUserInfo();
            appUserInfo.setMobilePhone(customerPhone);
            appUserInfo.setStationId(dto.getEnterpriseId());
            List<AppUserInfo> appUserInfos = appUserInfoService.selectAppUserInfoByMobilePhoneAndStationId(appUserInfo);


            if (appUserInfos.size() > 0) {
                AppUserInfo appUserInfo1 = appUserInfos.get(0);
                templateParams.put("openid", appUserInfo1.getBlogOpenid());
                templateParams.put("stationName", dto.getStationName());
                templateParams.put("productName", dto.getOilName());
                if (StringUtils.isNotEmpty(dto.getOilName())) {
                    Oil oil = oilMapper.selectOilById(new Long(dto.getOilName()));
                    templateParams.put("productName", oil.getOilName());
                }
                templateParams.put("amt", dto.getAmt().toString());
                templateParams.put("refundDate", simpleDateFormat.format(new Date()));
                wxPushUtil.sendTemplateMsg(dto.getEnterpriseId(), templateParams, WxTemplateEnum.REFUND_SUCCESS);
            }
        } else {
            log.info("参数不全,发送失败,dto:{}", dto);
            return;
        }
    }

    private void integralWxNotify(CustomerPointsRecord customerPointsRecord) {
        Map<String, String> templateParams = new HashMap<>();
        String customerPhone = customerPointsRecord.getMobilePhone();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (StringUtils.isNotEmpty(customerPhone) && customerPointsRecord.getStationId() != null) {
            Station station = stationMapper.selectStationById(customerPointsRecord.getStationId());

            AppUserInfo appUserInfo = new AppUserInfo();
            appUserInfo.setMobilePhone(customerPhone);
            appUserInfo.setStationId(station.getEnterpriseId());
            List<AppUserInfo> appUserInfos = appUserInfoService.selectAppUserInfoByMobilePhoneAndStationId(appUserInfo);
            if (appUserInfos.size() > 0) {
                AppUserInfo appUserInfo1 = appUserInfos.get(0);
                templateParams.put("openid", appUserInfo1.getBlogOpenid());
                templateParams.put("integral", customerPointsRecord.getRecordType() + customerPointsRecord.getIntegral().toString());
                templateParams.put("totalIntegral", appUserInfo1.getIntegral().toString());
                templateParams.put("stationName", station.getStationName());
                templateParams.put("createTime", simpleDateFormat.format(new Date()));
                log.info("积分变动-微信模板参数：{}", templateParams);
                wxPushUtil.sendTemplateMsg(station.getEnterpriseId(), templateParams, WxTemplateEnum.INTEGRAL_CHANGE);
            }
        } else {
            log.info("参数不全,发送失败,dto:{}", customerPointsRecord);
            return;
        }
    }

    @Override
    public void reductionActivityMessageSubscription(String message, WxConsumptionMessageEnum enums) {
        if (enums.equals(RECHARGE_REDUCTION_ACTIVITY)) {
            //参与充值立减活动
            if (StringUtils.isNotEmpty(message)) {
                com.platform.qujia.pojo.CustomerCardUseRecord customerCardUseRecord = JSONObject.parseObject(message, CustomerCardUseRecord.class);
                Station station = enterpriseService.selectStationById(customerCardUseRecord.getStationId());
                if (station == null) {
                    return;
                }
                boolean locked = false;
                String key = "DistributedLock_" + "reductionActivityMessageSubscription_" + RECHARGE_REDUCTION_ACTIVITY.getKey() + customerCardUseRecord.getMobilePhone();
                if (org.apache.commons.lang3.StringUtils.equals("1", station.getEnterprise().getCardUseRangeFlag())) {
                    key = key + station.getEnterpriseId();
                } else {
                    key = key + station.getStationId();
                }
                try {
                    locked = redisCacheUtil.lock(key, "locked", 5);
                    if (locked) {
                        Enterprise enterprise = enterpriseService.selectEnterpriseInfo(station.getEnterpriseId());
                        reductionActivityBalanceRecordService.createBalanceRecord(null,
                                customerCardUseRecord.getCardOilsType(),
                                customerCardUseRecord.getAmt(),
                                station,
                                null,
                                customerCardUseRecord.getMobilePhone(),
                                enterprise,
                                "xj"
                        );

                        couponController.sendCounponByCardUserRecord(customerCardUseRecord.getOrderNo());
                        //充值送积分
                        Integral integral = electronicMembershipCardService.rechargeActivityGiveIntegral(customerCardUseRecord);
                        if (StringUtils.equals("dtlr", customerCardUseRecord.getSource())) {
                            // 单条录入，推送消息
                            AppUserInfo userInfo = new AppUserInfo();
                            userInfo.setMobilePhone(customerCardUseRecord.getMobilePhone());
                            userInfo.setStationId(enterprise.getEnterpriseId());
                            userInfo = appUserInfoService.getAppUserInfo(userInfo);
                            if (userInfo != null && StringUtils.isNotBlank(userInfo.getBlogOpenid())) {
                                // 有用户，且有openid
                                CustomerElectronicCard card = electronicMembershipCardService.getCustomerElectronicCard(userInfo, customerCardUseRecord.getCardOilsType(), station);
                                if (card != null) {
                                    BalanceChangeWxNotifyDTO dto = new BalanceChangeWxNotifyDTO();
                                    dto.setEnterpriseId(enterprise.getEnterpriseId());
                                    dto.setOpenId(userInfo.getBlogOpenid());
                                    dto.setCustomerNo(userInfo.getMemberCode());
                                    dto.setAmt(customerCardUseRecord.getAmt());
                                    dto.setPresentAmt(customerCardUseRecord.getPresentAmt());
                                    dto.setBalance(card.getTotalAmt());
                                    dto.setPresentIntegral(integral.getPresentIntegral());
                                    dto.setTotalIntegral(integral.getTotalIntegral());
                                    dto.setStationName(station.getStationName());
                                    balanceChangeWxNotify(dto);
                                }
                            }
                        }

                    } else {
                        log.info("redis未获取锁");
                    }
                } finally {
                    if (locked) {
                        redisCacheUtil.unlock(key, "locked");
                    }
                }
            }
        }

    }

    private void monthlyConsumptionReportWxNotify(CustomerConsumptionReport dto) {
        Long enterpriseId = dto.getEnterpriseId();
        if (Objects.isNull(enterpriseId)) {
            //根据油站查油企
            Station station = stationMapper.selectStationById(dto.getStationId().intValue());
            enterpriseId = station.getEnterpriseId().longValue();
        }

        AppUserInfo userInfo = new AppUserInfo();
        userInfo.setMobilePhone(dto.getOpenId());
        userInfo.setStationId(enterpriseId.intValue());
        AppUserInfo info = appUserInfoMapper.getAppUserInfo(userInfo);
        dto.setOpenId(info.getBlogOpenid());


        Map<String, String> templateParams = new HashMap<>();

        templateParams.put("openid", dto.getOpenId());
        templateParams.put("stationName", dto.getStationName());
        templateParams.put("date", dto.getDate());
        templateParams.put("amtTotal", dto.getAmtTotal().toString());
        wxPushUtil.sendTemplateMsg(enterpriseId.intValue(), templateParams, WxTemplateEnum.MONTHLY_CONSUMPTION_REPORT);


    }
}
